/*
 * @(#)LifeCycle.java   1.0  2011-8-8
 * 
 * Copyright (c)	2010-2015. All Rights Reserved.	GuangDong Eshore Technology Company LTD.
 */
package com.swift.core.server;

import com.swift.core.spring.Spring;
import com.swift.exception.extend.SystemException;
import com.swift.util.type.IpUtil;
import com.swift.util.type.TypeUtil;

/**
 * 
 * 生命周期定义。实现该接口的类支持其定义的各个操作，如启动、停止。
 * 
 * @author jiajin
 * @version 1.0  2011-8-16
 */
public interface LifeCycle {
    
    public static String PORT_SPIT=":";
    
    public static String PORT_NAME="_port";
    /**
     * null 或者 -1 则为按服务自己配置端口
     * 输入(main protocol_port:80)> 服务配置 > 随机
     * @param port
     */
	public void start(int port);
	
	public boolean isStarted();
    
	public void stop();
	/**
	 * 获得本服务端口
	 * @return
	 */
    
	public int getPort();
	/**
	 * 默认端口
	 * @return
	 */
	public int defaultPort();
	/**
	 * 服务所属协议
	 * 一个协议只能一个服务
	 * @return
	 */
	public String protocol();
	
	default public String portKey() {
	    return protocol()+PORT_NAME;
	}
	/**
	 * 创建一个适用此协议的port
	 * 参数输入>配置文件>环境变量>默认端口>随机端口
	 * @param args
	 * @return
	 */
	default public int newPort(String[] args) {
	    Integer port = argsPort(args);
	    if(port!=null && port>0 && !IpUtil.checkLocalPort(port)) return port;
	    port = configPort();
	    if(port!=null && port>0 && !IpUtil.checkLocalPort(port)) return port;
	    port = defaultPort();
	    if(!IpUtil.checkLocalPort(port)) return port;
	    return randomPort();
	}
	/**
	 * 从输入参数获取服务端口
	 * @param args
	 * @return
	 */
	default public Integer argsPort(String[] args) {
	    if(args==null || args.length<=0) return null;
        for(String arg:args) {
            if(arg.startsWith(portKey()+LifeCycle.PORT_SPIT)) {
                String port = arg.replace(portKey()+LifeCycle.PORT_SPIT, "");
                if(TypeUtil.isNumber(port)) {
                    return TypeUtil.toInt(port);
                }
            }
        }
        return null;
	}
	
	/**
     * 从配置文件/环境变量获取服务端口
     * protocol_port:80
     * @return
     */
    default public Integer configPort() {
        Object port = Spring.getProperties().get(portKey());
        if(TypeUtil.isNumber(port)) return TypeUtil.toInt(port);
        // 系统参数
        port = System.getProperty(portKey());
        if(TypeUtil.isNumber(port)) return TypeUtil.toInt(port);
        // 环境变量
        port = System.getenv(portKey());
        if(TypeUtil.isNumber(port)) return TypeUtil.toInt(port);
        return null;
    }
    
    /**
     * 生成随机且没被占用的服务端口
     * 随机端口从30000起增
     * @return
     */
    default public int randomPort() {
        int min = 30000;
        int max = 65000;
        for(int port=min;port<max;port++) {
            if(!IpUtil.checkLocalPort(port)) return port;
        }
        throw new SystemException("端口已占用完毕");
    }
}
